// TCP文件传输服务端
#include "_public.h"

struct st_arg{
	int clienttype;		// 客户端类型，1-上传文件，2-下载文件
	char ip[31];
	int port;
	int ptype;			// 文件上传成功后文件的处理方式，1-删除文件，2-移动到备份目录
	char clientpath[301];
	char clientpathbak[301];
	bool andchild;		// 是否上传clientpath目录下各级子目录的文件
	char matchname[301];// 待上传文件名的匹配规则
	char srvpath[301];
	int timetvl;		// 扫描本地目录文件的时间间隔
	int timeout;		// 进程心跳的超时时间
	char pname[51];		// 进程名
} starg;

CLogFile logfile;      // 服务程序的运行日志
CTcpServer TcpServer;  // 创建服务端对象

char strrecvbuffer[1024], strsendbuffer[1024];

void FathEXIT(int sig);
void ChldEXIT(int sig);

bool _xmltoarg(char *strxmlbuffer);
bool ClientLogin();
void RecvFilesMain();

int main(int argc, char *argv[])
{
	if (argc != 4)
	{
		printf("Using:./demo14 port logfile \nExample:./demo14 5005 /tmp/demo14.log\n\n");
		return -1;
	}

	CloseIOAndSignal();
	signal(SIGINT, FathEXIT);
	signal(SIGTERM, FathEXIT);

	if (logfile.Open(argv[2],"a+")==false) { 
		printf("logfile.Open(%s) failed.\n",argv[2]); 
		return -1; 
	}

	// 服务端初始化
	if( TcpServer.InitServer(atoi(argv[1])) == false ){
		logfile.Write("TcpServer.InitServer(%s) failed.\n", argv[1]);
		return -1;
	}
	while (true)
	{
		// 等待客户端的连接请求
		if( TcpServer.Accept() == false ){
			logfile.Write("TcpServer.Accept() failed.\n");
			// return -1;
			FathEXIT(-1);
		}
		logfile.Write("客户端（%s）已连接\n", TcpServer.GetIP());

		
		// if(fork() > 0) {
		// 	TcpServer.CloseClient();
		// 	continue;
		// }

		// signal(SIGINT, ChldEXIT);
		// signal(SIGTERM, ChldEXIT);
		
		// TcpServer.CloseListen();

		// 处理登录客户端的登录报文
		if(ClientLogin() == false){
			ChldEXIT(-1);
		}

		// clienttype==1，调用上传文件的主函数
		if(starg.clienttype == 1){
			RecvFilesMain();
		}
		// clienttype==2，调用下载文件的主函数
		

		// return 0;
		ChldEXIT(0);
	}
}

void FathEXIT(int sig){
	// 以下代码是为了防止信号处理函数在执行的过程中被信号中断
	signal(SIGINT, SIG_IGN);
	signal(SIGTERM, SIG_IGN);

	logfile.Write("父进程退出,sig=%d\n", sig);
	TcpServer.CloseListen();
	kill(0,15);				// 通知全部的子进程退出
	exit(0);
}

void ChldEXIT(int sig){
	// 以下代码是为了防止信号处理函数在执行的过程中被信号中断
	signal(SIGINT, SIG_IGN);
	signal(SIGTERM, SIG_IGN);

	logfile.Write("子进程退出,sig=%d\n", sig);
	TcpServer.CloseClient();
	exit(0);
}


bool ClientLogin(){
	memset(strsendbuffer, 0, sizeof(strsendbuffer));
	memset(strrecvbuffer, 0, sizeof(strrecvbuffer));

	if(TcpServer.Read(strrecvbuffer, 20) == false){
		logfile.Write("TcpServer.Read() failed.\n", strrecvbuffer);
	}
	logfile.Write("strrecvbuffer=%s\n", strrecvbuffer);

	_xmltoarg(strrecvbuffer);

	// 检查clienttype是否合法
	if( (starg.clienttype != 1) && (starg.clienttype != 2) ){
		printf("%d",starg.clienttype);
		strcpy(strsendbuffer, "failed");
	}
	else {
		strcpy(strsendbuffer, "ok");
	}
	
	if(TcpServer.Write(strsendbuffer) == false){
		logfile.Write("TcpServer.Write() failed.\n", strsendbuffer);
	}
	logfile.Write("%s login %s\n", TcpServer.GetIP(), strsendbuffer);
	return true;
}

bool _xmltoarg(char *strxmlbuffer) {
	memset(&starg, 0, sizeof(struct st_arg));

	// 不需要对参数做合法性判断，客户端已经判断过了
	GetXMLBuffer(strxmlbuffer, "clienttype", &starg.clienttype);
	GetXMLBuffer(strxmlbuffer, "ptype", &starg.ptype);
	GetXMLBuffer(strxmlbuffer, "clientpath", starg.clientpath);
	GetXMLBuffer(strxmlbuffer, "andchild", &starg.andchild);
	GetXMLBuffer(strxmlbuffer, "matchname", starg.matchname);
	GetXMLBuffer(strxmlbuffer, "srvpath", starg.srvpath);

	GetXMLBuffer(strxmlbuffer, "timetvl", &starg.timetvl);
	if (starg.timetvl > 30)
		starg.timetvl = 30;

	GetXMLBuffer(strxmlbuffer, "timeout", &starg.timeout);
	if (starg.timeout < 50)
		starg.timeout = 50;

	GetXMLBuffer(strxmlbuffer, "pname", starg.pname, 50);
	strcat(starg.pname, "_srv");

	return true;
}

void RecvFilesMain(){
	while(true){
		memset(strsendbuffer, 0, sizeof(strsendbuffer));
		memset(strrecvbuffer, 0, sizeof(strrecvbuffer));

		// 接收客户端的报文
		if(TcpServer.Read(strrecvbuffer, starg.timetvl+10) == false){
			logfile.Write("TcpServer.Read() failed.\n");
			return;
		}
		logfile.Write("strrecvbuffer=%s.\n", strrecvbuffer);

		// 处理心跳报文
		if(strcmp(strrecvbuffer, "<activetest>ok</activetest>") == 0){
			strcpy(strsendbuffer, "ok");
			logfile.Write("strsendbuffer=%s\n", strsendbuffer);
			if(TcpServer.Write(strsendbuffer) == false){
				logfile.Write("TcpServer.Read() failed.\n");
				return;
			}
		}
	}
	
}